package com.ebraga.trackerclub.android.dao.core;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.database.Cursor;

import com.ebraga.trackerclub.android.dao.api.SyncDataDao;
import com.ebraga.trackerclub.android.dao.entity.SyncDataAndroid;
import com.ebraga.trackerclub.android.exception.BackofficeDBConnectionException;
import com.ebraga.trackerclub.android.exception.dao.BackofficeDaoException;
import com.ebraga.trackerclub.android.exception.dao.BackofficeIllegalArgumentDaoException;
import com.ebraga.trackerclub.android.util.ISmartServiceConstants;
import com.ebraga.trackerclub.android.util.api.AndroidContentValues;
import com.ebraga.trackerclub.android.util.api.DataAccessObject;

public abstract class SyncDataDaoImpl implements SyncDataDao {

	private DataAccessObject dataAccessObject;
	private AndroidContentValues contentValues;
	
	public SyncDataDaoImpl(DataAccessObject dataAccessObject) {
		this.dataAccessObject = dataAccessObject;
	}
	
	public void setContentValues(AndroidContentValues contentValues) {
		this.contentValues = contentValues;
	}

	private final static String[] SELECT_ALL_FIELDS = new String[] {
			ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_ID,
			ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_NAME,
			ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_LAST_TRY,
			ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_LAST_SUCCESS };

	@Override
	public Date updateLastTry(String name) throws BackofficeDaoException,
			BackofficeDBConnectionException, BackofficeIllegalArgumentDaoException {
		
		SyncDataAndroid syncDataAndroid = getSyncData(name);
		if(syncDataAndroid == null)
			throw new BackofficeIllegalArgumentDaoException("Parameter with name '"+name+"' not found.");
		
		try{
			Date lastTry = new Date();
			
			syncDataAndroid.setLastTryDateTime(lastTry.getTime());
			contentValues = createRecord(syncDataAndroid);
			String whereClause = ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_ID + "=?";
			
			dataAccessObject.getDB().update(ISmartServiceConstants.DATABASE.SYNCDATA.TABLE_NAME, contentValues, whereClause, new String[]{syncDataAndroid.getXidSyncData().toString()});
			
			return lastTry;
			
		} catch (BackofficeDBConnectionException e) {
			throw new BackofficeDBConnectionException("Erro ao conectar banco de dados", e);
		}catch (BackofficeDaoException e){
			throw e;
		}catch(Exception e){
			throw new BackofficeDaoException("Erro ao executar query", e);
		}
	}

	@Override
	public Date updateLastSuccess(String name) throws BackofficeDaoException,
			BackofficeDBConnectionException, BackofficeIllegalArgumentDaoException {
		
		SyncDataAndroid syncDataAndroid = getSyncData(name);
		if(syncDataAndroid == null)
			throw new BackofficeIllegalArgumentDaoException("Parameter with name '"+name+"' not found.");
		
		try{
			Date lastSuccess = new Date();
			
			syncDataAndroid.setLastSuccessDateTime(lastSuccess.getTime());
			contentValues = createRecord(syncDataAndroid);
			String whereClause = ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_ID + " = ? ";
			
			dataAccessObject.getDB().update(ISmartServiceConstants.DATABASE.SYNCDATA.TABLE_NAME, contentValues, whereClause, new String[]{syncDataAndroid.getXidSyncData().toString()});
			
			return lastSuccess;
			
		} catch (BackofficeDBConnectionException e) {
			throw new BackofficeDBConnectionException("Erro ao conectar banco de dados", e);
		}catch (BackofficeDaoException e){
			throw e;
		}catch(Exception e){
			throw new BackofficeDaoException("Erro ao executar query", e);
		}
	}

	@Override
	public SyncDataAndroid getSyncData(String name) throws BackofficeDaoException,
			BackofficeDBConnectionException, BackofficeIllegalArgumentDaoException {
		
		if (name == null){
			throw new BackofficeIllegalArgumentDaoException("Name cannot be null");
		}
		
		Cursor cursor = null;
		try{
			String where = ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_NAME + "=?";
			String[] whereArgs = new String[] {name}; 
			
			cursor = dataAccessObject.getDB().query(ISmartServiceConstants.DATABASE.SYNCDATA.TABLE_NAME, SELECT_ALL_FIELDS, where, whereArgs, null, null, null);
			List<SyncDataAndroid> recordsFromCursor = new ArrayList<SyncDataAndroid>(getRecordsFromCursor(cursor));
			
			return !recordsFromCursor.isEmpty() ? recordsFromCursor.get(0) : null;
			
		} catch (BackofficeDBConnectionException e) {
			throw new BackofficeDBConnectionException("Erro ao conectar banco de dados", e);
		}catch (BackofficeDaoException e){
			throw e;
		}catch(Exception e){
			throw new BackofficeDaoException("Erro ao executar query", e);
		} finally {
			if(cursor != null)
				cursor.close();
		}
	}
	
	private synchronized AndroidContentValues createRecord(SyncDataAndroid syncDataAndroid) {
		
		contentValues.put(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_ID, syncDataAndroid.getXidSyncData());
		contentValues.put(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_NAME, syncDataAndroid.getName());
		contentValues.put(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_LAST_TRY, syncDataAndroid.getLastTryDateTime());
		contentValues.put(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_LAST_SUCCESS, syncDataAndroid.getLastSuccessDateTime());
		
		return contentValues;
	}
	
	private List<SyncDataAndroid> getRecordsFromCursor(Cursor cursor) {
		
		List<SyncDataAndroid> result = new ArrayList<SyncDataAndroid>();
		while (cursor.moveToNext()) {
			SyncDataAndroid syncDataAndroid = new SyncDataAndroid();
			syncDataAndroid.setXidSyncData(cursor.getInt(cursor.getColumnIndexOrThrow(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_ID)));
			syncDataAndroid.setName(cursor.getString(cursor.getColumnIndexOrThrow(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_NAME)));
			syncDataAndroid.setLastTryDateTime(cursor.getLong(cursor.getColumnIndexOrThrow(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_LAST_TRY)));
			syncDataAndroid.setLastSuccessDateTime(cursor.getLong(cursor.getColumnIndexOrThrow(ISmartServiceConstants.DATABASE.SYNCDATA.FIELD_LAST_SUCCESS)));

			result.add(syncDataAndroid);
		}

		return result;
	}	
}
